{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "%run startup.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "$.getScript('./assets/js/ipython_notebook_toc.js')"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%javascript\n",
    "$.getScript('./assets/js/ipython_notebook_toc.js')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# A Decision Tree of Observable Operators\n",
    "\n",
    "## Part 3: Transformation\n",
    "\n",
    "> source: http://reactivex.io/documentation/operators.html#tree.  \n",
    "> (transcribed to RxPY 1.5.7, Py2.7 / 2016-12, Gunther Klessinger, [axiros](http://www.axiros.com))  \n",
    "\n",
    "**This tree can help you find the ReactiveX Observable operator you’re looking for.**  \n",
    "See [Part 1](./A Decision Tree of Observable Operators. Part I - Creation.ipynb) for Usage and Output Instructions.  \n",
    "\n",
    "We also require acquaintance with the [marble diagrams](./Marble Diagrams.ipynb) feature of RxPy.\n",
    "\n",
    "<h2 id=\"tocheading\">Table of Contents</h2>\n",
    "<div id=\"toc\"></div>\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# I want emit the items from an Observable after **transforming** them\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ... one at a time with a function **[map / pluck / pluck_attr](http://reactivex.io/documentation/operators/map.html) **"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "========== map ==========\n",
      "\n",
      "function select of module rx.linq.observable.select:\n",
      "Project each element of an observable sequence into a new form\n",
      "    by incorporating the element's index.\n",
      "\n",
      "    1 - source.map(lambda value: value * value)\n",
      "    2 - source.map(lambda value, index: value * value + index)\n",
      "\n",
      "    Keyword arguments:\n",
      "    :param Callable[[Any, Any], Any] selector: A transform function to\n",
      "        apply to each source element; the second parameter of the\n",
      "        function represents the index of the source element.\n",
      "    :rtype: Observable\n",
      "\n",
      "    Returns an observable sequence whose elements are the result of\n",
      "    invoking the transform function on each element of source.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.6     M New subscription on stream 276083189\n",
      "   2.1     M [next]    1.5: 2\n",
      "   2.5     M [next]    1.9: 4\n",
      "   3.0     M [next]    2.4: 6\n",
      "   3.3     M [cmpl]    2.7: fin\n"
     ]
    }
   ],
   "source": [
    "reset_start_time(O.map, title='map') # alias is \"select\"\n",
    "# warming up:\n",
    "d = subs(O.from_((1, 2 , 3)).map(lambda x: x * 2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "========== pluck ==========\n",
      "\n",
      "function pluck of module rx.linq.observable.pluck:\n",
      "Retrieves the value of a specified key using dict-like access (as in\n",
      "    element[key]) from all elements in the Observable sequence.\n",
      "\n",
      "    Keyword arguments:\n",
      "    key {String} The key to pluck.\n",
      "\n",
      "    Returns a new Observable {Observable} sequence of key values.\n",
      "\n",
      "    To pluck an attribute of each element, use pluck_attr.\n",
      "\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   1.0     M New subscription on stream 276081749\n",
      "   1.8     M [next]    0.6: 2\n",
      "   2.2     M [next]    1.0: 4\n",
      "   2.5     M [cmpl]    1.3: fin\n",
      "\n",
      "\n",
      "========== pluck_attr ==========\n",
      "\n",
      "\n",
      "   0.4     M New subscription on stream 276081825\n",
      "   0.6     M [next]    0.2: 2\n",
      "   0.8     M [next]    0.4: 4\n",
      "   1.0     M [cmpl]    0.6: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.pluck, title='pluck')\n",
    "d = subs(O.from_([{'x': 1, 'y': 2}, {'x': 3, 'y': 4}]).pluck('y'))\n",
    "\n",
    "class Coord:\n",
    "    def __init__(self, x, y): \n",
    "        self.x = x\n",
    "        self.y = y\n",
    "rst(title='pluck_attr')        \n",
    "d = subs(O.from_([Coord(1, 2), Coord(3, 4)]).pluck_attr('y'))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ...by emitting all of the items emitted by corresponding Observables"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### **[flat_map(select_many)](http://reactivex.io/documentation/operators/flatmap.html)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function select_many of module rx.linq.observable.selectmany:\n",
      "One of the Following:\n",
      "    Projects each element of an observable sequence to an observable\n",
      "    sequence and merges the resulting observable sequences into one\n",
      "    observable sequence.\n",
      "\n",
      "    1 - source.select_many(lambda x: Observable.range(0, x))\n",
      "\n",
      "    Or:\n",
      "    Projects each element of an observable sequence to an observable\n",
      "    sequence, invokes the result selector for the source element and each\n",
      "    of the corresponding inner sequence's elements, and merges the results\n",
      "    into one observable sequence.\n",
      "\n",
      "    1 - source.select_many(lambda x: Observable.range(0, x), lambda x, y: x + y)\n",
      "\n",
      "    Or:\n",
      "    Projects each element of the source observable sequence to the other\n",
      "    observable sequence and merges the resulting observable sequences into\n",
      "    one observable sequence.\n",
      "\n",
      "    1 - source.select_many(Observable.from_([1,2,3]))\n",
      "\n",
      "    Keyword arguments:\n",
      "    selector -- A transform function to apply to each element or an\n",
      "        observable sequence to project each element from the source\n",
      "        sequence onto.\n",
      "    result_selector -- [Optional] A transform function to apply to each\n",
      "        element of the intermediate sequence.\n",
      "\n",
      "    Returns an observable sequence whose elements are the result of\n",
      "    invoking the one-to-many transform function collectionSelector on each\n",
      "    element of the input sequence and then mapping each of those sequence\n",
      "    elements and their corresponding source element to a result element.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.5     M New subscription on stream 275034569\n",
      "   2.2     M [next]    1.4: 1\n",
      "   2.9     M [next]    2.1: 2\n",
      "   3.0     M [next]    2.3: 2\n",
      "   3.5     M [next]    2.8: 3\n",
      "   3.9     M [cmpl]    3.1: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.flat_map)\n",
    "stream = O.range(1, 2)\\\n",
    "           .flat_map(lambda x: O.range(x, 2)) # alias: select_many\n",
    "d = subs(stream)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "   0.4     M New subscription on stream 276591581\n",
      "   1.6     M [next]    1.0: a\n",
      "   2.5     M [next]    1.9: b\n",
      "   3.5     M [next]    2.9: c\n",
      "   4.0     M [cmpl]    3.5: fin\n",
      "\n",
      "   4.5     M New subscription on stream 276589117\n",
      "   5.2     M [next]    0.6: a\n",
      "   5.6     M [next]    1.0: 0\n",
      "   5.9     M [next]    1.2: b\n",
      "   6.5     M [next]    1.8: 1\n",
      "   7.0     M [next]    2.4: c\n",
      "   7.9     M [next]    3.3: 2\n",
      "   8.7     M [cmpl]    4.1: fin\n",
      "\n",
      "\n",
      "========== using a result selector ==========\n",
      "\n",
      "\n",
      "  10.1     M New subscription on stream 276589129\n",
      "  11.0     M [next]    0.7: a-a-0\n",
      "  11.8     M [next]    1.5: a-0-1\n",
      "  12.0     M [next]    1.7: b-b-0\n",
      "  12.9     M [next]    2.6: b-1-1\n",
      "  13.1     M [next]    2.9: c-c-0\n",
      "  14.3     M [next]    4.0: c-2-1\n",
      "  15.0     M [cmpl]    4.7: fin\n",
      "\n",
      "  15.9     M New subscription on stream 276582045\n",
      "  17.2     M [next]    1.0: a-a-0\n",
      "  18.4     M [next]    2.2: a-0-1\n",
      "  18.8     M [next]    2.6: b-b-0\n",
      "  20.0     M [next]    3.8: b-1-1\n",
      "  20.7     M [next]    4.5: c-c-0\n",
      "  21.4     M [next]    5.2: c-2-1\n",
      "  22.0     M [cmpl]    5.8: fin\n"
     ]
    }
   ],
   "source": [
    "rst() # from an array\n",
    "s1 = O.from_(('a', 'b', 'c'))\n",
    "d  = subs(s1.flat_map(lambda x: x))\n",
    "d  = subs(s1.flat_map(lambda x, i: (x, i)))\n",
    "#d = subs(O.from_(('a', 'b', 'c')).flat_map(lambda x, i: '%s%s' % (x, i))) # ident, a string is iterable\n",
    "\n",
    "header('using a result selector')\n",
    "\n",
    "def res_sel(*a):\n",
    "    # in conrast to the RxJS example I get only 3 parameters, see output\n",
    "    return '-'.join([str(s) for s in a])\n",
    "\n",
    "# for every el of the original stream we get *additional* two elements: the el and its index:\n",
    "d = subs(s1.flat_map(lambda x, i: (x, i)         , res_sel))\n",
    "# ident, flat_map flattens the inner stream:\n",
    "d = subs(s1.flat_map(lambda x, i: O.from_((x, i)), res_sel))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### **[flat_map_latest(select_switch)](http://reactivex.io/documentation/operators/flatmap.html)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function select_switch of module rx.linq.observable.selectswitch:\n",
      "Projects each element of an observable sequence into a new sequence\n",
      "    of observable sequences by incorporating the element's index and then\n",
      "    transforms an observable sequence of observable sequences into an\n",
      "    observable sequence producing values only from the most recent\n",
      "    observable sequence.\n",
      "\n",
      "    Keyword arguments:\n",
      "    selector -- {Function} A transform function to apply to each source\n",
      "        element; the second parameter of the function represents the index\n",
      "        of the source element.\n",
      "\n",
      "    Returns an observable {Observable} sequence whose elements are the\n",
      "    result of invoking the transform function on each element of source\n",
      "    producing an Observable of Observable sequences and that at any point in\n",
      "    time produces the elements of the most recent inner observable sequence\n",
      "    that has been received.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.5     M New subscription on stream 276552361\n",
      "   1.6     M [next]    1.0: 1\n",
      "   2.4     M [next]    1.8: 2\n",
      "   2.7     M [next]    2.1: 3\n",
      "   3.0     M [cmpl]    2.5: fin\n",
      "\n",
      "   3.8     M New subscription on stream 274776265\n",
      "   4.5     M [next]    0.5: A0-a\n",
      "   5.2     M [next]    1.3: B1-a\n",
      "   5.6     M [next]    1.7: C2-a\n",
      "   6.0     M [next]    2.1: C2-b\n",
      "   6.3     M [next]    2.3: C2-c\n",
      "   6.5     M [cmpl]    2.5: fin\n",
      "\n",
      "   7.2     M New subscription on stream 276554429\n",
      "  29.4  T140 [next]   22.1: Aa\n",
      " 142.3  T142 [next]  135.0: Ab\n",
      " 240.7  T148 [next]  233.4: Ba\n",
      " 355.5  T149 [next]  348.2: Bb\n",
      " 456.5  T156 [next]  449.3: Ca\n",
      " 570.4  T157 [next]  563.1: Cb\n",
      " 677.2  T159 [next]  669.9: Cc\n",
      " 688.4  T161 [cmpl]  681.1: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.flat_map_latest) # alias: select_switch\n",
    "\n",
    "d = subs(O.range(1, 2).flat_map_latest(lambda x: O.range(x, 2)))\n",
    "\n",
    "# maybe better to understand: A, B, C are emitted always more recent, then the inner streams' elements\n",
    "d = subs(O.from_(('A', 'B', 'C')).flat_map_latest(\n",
    "        lambda x, i: O.from_(('%s%s-a' % (x, i),\n",
    "                              '%s%s-b' % (x, i),\n",
    "                              '%s%s-c' % (x, i),\n",
    "                             ))))\n",
    "\n",
    "# with emission delays: Now the inner's is faster:\n",
    "outer = O.from_marbles('A--B--C|').to_blocking()\n",
    "inner = O.from_marbles('a-b-c|').to_blocking()\n",
    "# the inner .map is to show also outer's value\n",
    "d = subs(outer.flat_map_latest(lambda X: inner.map(lambda x: '%s%s' % (X, x))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### **[concat_map](http://reactivex.io/documentation/operators/flatmap.html)**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function for_in of module rx.linq.observable.forin:\n",
      "Concatenates the observable sequences obtained by running the\n",
      "    specified result selector for each element in source.\n",
      "\n",
      "    sources -- {Array} An array of values to turn into an observable\n",
      "        sequence.\n",
      "    result_selector -- {Function} A function to apply to each item in the\n",
      "        sources array to turn it into an observable sequence.\n",
      "    Returns an observable {Observable} sequence from the concatenated\n",
      "    observable sequences.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.9     M New subscription on stream 276573325\n",
      "  12.3   T28 [next]   11.2: a1\n",
      " 122.9   T29 [next]  121.7: b1\n",
      " 147.8   T34 [next]  146.6: a2\n",
      " 261.4   T36 [next]  260.2: b2\n",
      " 284.2   T40 [next]  283.0: a3\n",
      " 394.4   T41 [next]  393.3: b3\n",
      " 404.6   T42 [cmpl]  403.4: fin\n",
      "\n",
      " 505.1     M New subscription on stream 276563949\n",
      " 517.7   T46 [next]   12.6: a<rx.core.anonymousobservable.AnonymousObservable object at 0x107c21710>\n",
      " 627.3   T48 [next]  122.2: b<rx.core.anonymousobservable.AnonymousObservable object at 0x107c21710>\n",
      " 628.0   T48 [cmpl]  122.9: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.for_in)\n",
    "abc = O.from_marbles('a-b|').to_blocking()\n",
    "\n",
    "# abc times 3, via:\n",
    "d = subs(O.for_in([1, 2, 3],\n",
    "                  lambda i: abc.map(\n",
    "                      # just to get the results of array and stream:\n",
    "                      lambda letter: '%s%s' % (letter, i) )))\n",
    "sleep(0.5)\n",
    "# we can also for_in from an observable.\n",
    "# TODO: Dont' understand the output though - __doc__ says only arrays.\n",
    "d = subs(O.for_in(O.from_((1, 2, 3)),\n",
    "                  lambda i: abc.map(lambda letter: '%s%s' % (letter, i) )).take(2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### **[many_select](http://reactivex.io/documentation/operators/flatmap.html)**\n",
    "manySelect internally transforms each item emitted by the source Observable into an Observable that emits that item and all items subsequently emitted by the source Observable, in the same order.  \n",
    "\n",
    "So, for example, it internally transforms an Observable that emits the numbers 1,2,3 into three Observables: one that emits 1,2,3, one that emits 2,3, and one that emits 3.\n",
    "\n",
    "Then manySelect passes each of these Observables into a function that you provide, and emits, as the emissions from the Observable that manySelect returns, the return values from those function calls.\n",
    "\n",
    "In this way, each item emitted by the resulting Observable is a function of the corresponding item in the source Observable and all of the items emitted by the source Observable after it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function many_select of module rx.linq.observable.manyselect:\n",
      "Comonadic bind operator. Internally projects a new observable for each\n",
      "    value, and it pushes each observable into the user-defined selector function\n",
      "    that projects/queries each observable into some result.\n",
      "\n",
      "    Keyword arguments:\n",
      "    selector -- {Function} A transform function to apply to each element.\n",
      "    scheduler -- {Object} [Optional] Scheduler used to execute the\n",
      "        operation. If not specified, defaults to the ImmediateScheduler.\n",
      "\n",
      "    Returns {Observable} An observable sequence which results from the\n",
      "    comonadic bind operation.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   1.0     M New subscription on stream 276604289\n",
      "  13.0  T196 [next]   11.7: a\n",
      " 123.5  T197 [next]  122.2: b\n",
      " 234.1  T200 [next]  232.8: c\n",
      " 246.1  T202 [cmpl]  244.7: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.many_select) \n",
    "stream = O.from_marbles('a-b-c|')\n",
    "# TODO: more use cases\n",
    "d = subs(stream.many_select(lambda x: x.first()).merge_all())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ... based on ALL of the items that preceded them **[scan](http://reactivex.io/documentation/operators/scan.html) **"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function scan of module rx.linq.observable.scan:\n",
      "Applies an accumulator function over an observable sequence and\n",
      "    returns each intermediate result. The optional seed value is used as\n",
      "    the initial accumulator value. For aggregation behavior with no\n",
      "    intermediate results, see Observable.aggregate.\n",
      "\n",
      "    1 - scanned = source.scan(lambda acc, x: acc + x)\n",
      "    2 - scanned = source.scan(lambda acc, x: acc + x, 0)\n",
      "\n",
      "    Keyword arguments:\n",
      "    accumulator -- An accumulator function to be invoked on each element.\n",
      "    seed -- [Optional] The initial accumulator value.\n",
      "\n",
      "    Returns an observable sequence containing the accumulated values.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.7     M New subscription on stream 276601945\n",
      "  14.1  T240 [next]   13.1: 10001\n",
      " 128.1  T242 [next]  127.0: 10003\n",
      " 234.7  T243 [next]  233.6: 10006\n",
      " 345.3  T246 [next]  344.3: 10010\n",
      " 656.9  T247 [next]  655.8: 10015\n",
      " 657.6  T249 [cmpl]  656.5: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.scan)\n",
    "s = O.from_marbles(\"1-2-3-4---5\").to_blocking()\n",
    "d = subs(s.scan(lambda x, y: int(x) + int(y), seed=10000))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ... by attaching a timestamp to them **[timestamp](http://reactivex.io/documentation/operators/timestamp.html) **"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function timestamp of module rx.linq.observable.timestamp:\n",
      "Records the timestamp for each value in an observable sequence.\n",
      "\n",
      "    1 - res = source.timestamp() # produces { \"value\": x, \"timestamp\": ts }\n",
      "    2 - res = source.timestamp(Scheduler.timeout)\n",
      "\n",
      "    :param Scheduler scheduler: [Optional] Scheduler used to compute timestamps. If not\n",
      "        specified, the timeout scheduler is used.\n",
      "\n",
      "    Returns an observable sequence with timestamp information on values.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.7     M New subscription on stream 276594097\n",
      "  12.1  T276 [next]   11.2: 2016-12-20 20:23:22.236924\n",
      " 122.7  T277 [next]  121.8: 2016-12-20 20:23:22.347565\n",
      " 235.4  T279 [next]  234.5: 2016-12-20 20:23:22.460266\n",
      " 244.0  T281 [cmpl]  243.1: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.timestamp)\n",
    "# the timestamps are objects, not dicts:\n",
    "d = subs(marble_stream('a-b-c|').timestamp().pluck_attr('timestamp'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ... into an indicator of the amount of time that lapsed before the emission of the item **[time_interval](http://reactivex.io/documentation/operators/timeinterval.html) **"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "function time_interval of module rx.linq.observable.timeinterval:\n",
      "Records the time interval between consecutive values in an\n",
      "    observable sequence.\n",
      "\n",
      "    1 - res = source.time_interval();\n",
      "    2 - res = source.time_interval(Scheduler.timeout)\n",
      "\n",
      "    Keyword arguments:\n",
      "    scheduler -- [Optional] Scheduler used to compute time intervals. If\n",
      "        not specified, the timeout scheduler is used.\n",
      "\n",
      "    Return An observable sequence with time interval information on values.\n",
      "    \n",
      "--------------------------------------------------------------------------------\n",
      "\n",
      "   0.8     M New subscription on stream 276593965\n",
      "  12.7  T316 [next]   11.8: 0:00:00.011533\n",
      " 127.7  T318 [next]  126.8: 0:00:00.115022\n",
      " 339.1  T319 [next]  338.2: 0:00:00.211367\n",
      " 344.4  T322 [cmpl]  343.6: fin\n"
     ]
    }
   ],
   "source": [
    "rst(O.time_interval)\n",
    "d = subs(marble_stream('a-b--c|').time_interval().map(lambda x: x.interval))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
